package advancedpart.assignmentA3;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;

import shared.SearchOperator;
import shared.WordElement;

/**
 * Programming workshop advanced part assignment 3
 * 
 * Methods for creating hashtables for text files and search for 
 * a given word:
 * 
 */
public class SearcherA3 {

	/**
	 * getUrls searches through a HashMap for two words and prints the urls 
	 * they have i common using an operator. Depending on the operator either 
	 * the urls the words has in common or the urls where they both appear.
	 * 
	 * @param map hashmap to search through
	 * @param word1 first word
	 * @param word2 second word
	 * @param operator either AND or OR
	 *  
	 * @return urls
	 */
	@SuppressWarnings("unchecked")
	public static String getUrls(HashMap<String, WordElement> map, String word1, String word2, SearchOperator operator)
	{
		//Create return variable
		String urlString = "";
		
		//Create set for set operations.
		HashSet<String> urls = new HashSet<String>();

		//Get the first word
		WordElement element1 = map.get(word1);
		
		//Create variable for the first words urls
		HashSet<String> element1Urls;
		
		//check for null to avoid NullPointerExecption if the word is not found in the map
		if(element1 != null){
			element1Urls = (HashSet<String>) element1.urls.clone();
		} else {
			element1Urls = new HashSet<String>();
		}

		//Get the second word 
		WordElement element2 = map.get(word2);
		
		//Create set for the second words urls
		HashSet<String> element2Urls;	
		
		//check for null to avoid NullPointerExecption if the word is not found in the map
		if(element2 != null){ 
			element2Urls = (HashSet<String>) element2.urls.clone();
		} else {
			element2Urls = new HashSet<String>();
		}

		//Check what algorithm to use depending on the operator
		switch(operator){
		case AND: 	
			//Add the first set of urls
			urls.addAll(element1Urls);
			
			//Get the intersection of the two sets
			urls.retainAll(element2Urls);
			
			//Get string value
			urlString = urls.toString();
			
			//Break switch
			break;

		case OR:
			//Add the first set of urls
			urls.addAll(element1Urls);
			
			//Get the union of the two sets
			urls.addAll(element2Urls);
			
			//Get string value
			urlString = urls.toString();
			
			//Break switch
			break;

		default: 
			break;
		}

		//Return the found urls
		return urlString;
	}


	/**
	 * createWordMap reads a text file and returns a HashMap where 
	 * each unique word String in the text file has an unique position 
	 * in the HashMap and a set of all the urls in the text file
	 * where the word is found 
	 * 
	 * @param filename the file name and path of the file
	 * @return the map with the words
	 * @throws IOException
	 */
	public static HashMap<String, WordElement> createWordMap(String filename) throws IOException {

		//Variables for constructing the HashMap
		String name; 
		String currentUrl = "";

		//Create the returned map
		HashMap<String, WordElement> wordMap = new HashMap<String, WordElement>();

		//Load the text file
		BufferedReader infile = new BufferedReader(new FileReader(filename));

		//Read the first line
		name = infile.readLine();
		
		// Iterate through lines
		while (name != null) {
			if ( !(name.startsWith("*PAGE")) ) {  //line contains word	
				
				//Get lower cased version of the word
				String nameLowerCased = name.toLowerCase();
				
				//Try the get the word in the HashMap
				WordElement wordsAtKey = wordMap.get(nameLowerCased);							
				
				if (wordsAtKey != null) {// Check if words in map already
					wordsAtKey.addUrl(currentUrl);					
					
				} else { //If it's a new unique word					
					//Create new element 
					WordElement newElement = new WordElement(nameLowerCased);
					newElement.addUrl(currentUrl);
					
					// insert new WordList element with UrlList element
					wordMap.put(nameLowerCased, newElement);
				}							
			} else {  // line contains Url							
				currentUrl = name.substring(6);							 
			}						
			// read next line of file
			name = infile.readLine();
		}					

		//Return data set
		return wordMap;
	}	

}


